'''
Created on Mar 23, 2013

@author: Petko
'''
import urllib2
from urllib import urlencode
import json
from urllib2 import HTTPError
import time

class SententialyzerClient:
    '''
    classdocs
    '''


    def __init__(self, base_addr=None):
        '''
        Constructor
        '''
        if base_addr:
            self.base_addr = base_addr
        else:
            #self.base_addr = 'http://127.0.0.1'
            self.base_addr = 'http://127.0.0.1:8000'
            #self.base_addr = 'http://sententialyzer-petkop.rhcloud.com'
            
        self.commenterId = 1
        self.accessToken = None
        
    def sendReq(self, url, method = 'POST', query = {}):
        queryData = urlencode(query)
        try:
            if method == 'POST':
                result = urllib2.urlopen(url, queryData)
            else:
                if queryData:
                    url += '?' + queryData
                result = urllib2.urlopen(url)
        except HTTPError as e:
            print e.read()
            raise
        return result
        
    def authorize(self, username, password, scopes):
        url = self.base_addr + '/auth/authorize'
        
        postData = {'user_id': username, 'password': password, 'scope': scopes }
        result = self.sendReq(url, 'POST', postData)
        
        resultJson = json.load(result)
        self.accessToken = resultJson['access_token'] 
        return self.accessToken
    
    def createGroup(self, groupId, groupData, permissions):
        url = self.base_addr + '/group/create'
        postData = {'access_token': self.accessToken, 
                     'group_id': groupId,
                     'group_data': groupData,
                     'permissions': permissions}
        
        result = self.sendReq(url, 'POST', postData)
        return json.load(result)
    
    def addUserToGroup(self, userId, groupId):
        url = self.base_addr + '/group/add_user'
        
        postData = {'access_token': self.accessToken, 
                    'user_id': userId,
                    'group_id': groupId}
        
        result = self.sendReq(url, 'POST', postData)
        return json.load(result)
    
    def removeUserFromGroup(self, userId, groupId):
        url = self.base_addr + '/group/remove_user'
        
        postData = {'access_token': self.accessToken, 
                    'user_id': userId,
                    'group_id': groupId}
        
        result = self.sendReq(url, 'POST', postData)
        return json.load(result)
    
    def getGroupUsers(self, groupId, **kwargs):
        url = self.base_addr + '/group/get_group_users'
        query = {'access_token': self.accessToken, 
                 'group_id': groupId}
        query.update(kwargs)
        
        result = self.sendReq(url, 'GET', query)
        return json.load(result)
    
    def getUserGroups(self, userId, **kwargs):
        url = self.base_addr + '/group/get_user_groups'
        query = {'access_token': self.accessToken, 
                 'user_id': userId}
        query.update(kwargs)
        result = self.sendReq(url, 'GET', query)
        return json.load(result)
    
    def createBaseOp(self, title, content, groupPermissions):
        url = self.base_addr + '/opinion/create_base_opinion'
        query = {'access_token': self.accessToken, 
                 'title': title,
                 'content': content,
                 'group_permissions': groupPermissions}
        
        result = self.sendReq(url, 'POST', query)
        return json.load(result)
    
    def deleteBaseOp(self, opId):
        url = self.base_addr + '/opinion/delete_base_opinion'
        query = {'access_token': self.accessToken, 'opinion_id': opId}
        result = self.sendReq(url, 'POST', query)
        return json.load(result)
    
    def viewListOp(self, view, order, **kwargs):
        url = self.base_addr + '/view/list_opinions'
        query = {'view_id': view,
                 'order' : order}
        
        query.update(kwargs)
        
        result = self.sendReq(url, 'GET', query)
        return json.load(result)
    
    def postCreateView(self, viewId, groupPermissions):
        url = self.base_addr + '/view/create'
        query = {'access_token': self.accessToken,
                 'view_id' : viewId,
                 'group_permissions': groupPermissions}
        
        result = self.sendReq(url, 'POST', query)
        return json.load(result)
    def postDeleteView(self, viewId):
        url = self.base_addr + '/view/delete'
        query = {'access_token': self.accessToken,
                 'view_id' : viewId}
        
        result = self.sendReq(url, 'POST', query)
        return json.load(result)
    
    def createOp(self, parent, evaluation, commit_pending_ops=True, **kwargs):
        url = self.base_addr + '/opinion/create_opinion'
        query = {'access_token': self.accessToken,
                 'parent' : parent,
                 'evaluation': evaluation}
        
        query.update(kwargs)
        
        result = self.sendReq(url, 'POST', query)
        result_json = json.load(result)
        
        if commit_pending_ops:
            self.commit_pending_ops()
        
        return result_json['opinion']
    
    def getOpSimple(self, opId, order, subopinions_only = 0, max_content_length = 0, tree_order='breadth_first', max_depth = 5, skip_empty = 0, **kwargs):
        url = self.base_addr + '/opinion/get'
        
        query = {'opinion_id': opId,
                 
                 'max_content_length': max_content_length,
                 'subopinions_only': subopinions_only}
        
        if self.accessToken:
            query['access_token'] = self.accessToken
        
        if max_depth:
            subop_desc = {'tree_order': tree_order,
                          'order': order,
                          'max_depth': max_depth,
                          'max_content_length': max_content_length,
                          'skip_empty': skip_empty}
            
            subop_desc.update(kwargs)
            
            query['subopinions_desc'] = json.dumps(subop_desc)
        
        result = self.sendReq(url, 'GET', query)
        return json.load(result)
    
    def getOpExt(self, opId, subopinions_desc, **kwargs):
        
        url = self.base_addr + '/opinion/get'
        
        if not subopinions_desc.has_key('skip_empty'):
            subopinions_desc['skip_empty'] = 0
        
        query = {'opinion_id': opId,
                 'subopinions_desc': json.dumps(subopinions_desc) }
        
        if self.accessToken:
            query['access_token'] = self.accessToken
        
        query.update(kwargs)
        
        result = self.sendReq(url, 'GET', query)
        return json.load(result)
                 
    def getUserOp(self, base_id, order, **kwargs):
        url = self.base_addr + '/opinion/get_user_opinions'
        query = {'base_id': base_id,
                 'access_token' : self.accessToken,
                 'order': order}
        query.update(kwargs)
        
        result = self.sendReq(url, 'GET', query)
        return json.load(result)
    
    def commit_pending_ops(self, print_time=False, **kwargs):
        time_start = time.time()
        result = self.sendReq(self.base_addr + '/opinion/process_nested_set', 'POST', kwargs)
        
        if print_time:
            print "commit_pending_ops time ", time.time() - time_start, " sec"
        
        return json.load(result)
    
    def updateOp(self, opId, commit_pending_ops=True, **kwargs):
        url = self.base_addr + '/opinion/update'
        query = {'opinion_id': opId,
                 'access_token' : self.accessToken}
        
        query.update(kwargs)
        
        result = self.sendReq(url, 'POST', query)
        result_json = json.load(result)
        
        if commit_pending_ops:
            self.commit_pending_ops()
            
        return result_json
    
    def deleteOp(self, opId, commit_pending_ops=True, commit_delay=0):
        url = self.base_addr + '/opinion/delete'
        query = {'opinion_id': opId,
                 'access_token' : self.accessToken,
                 'commit_delay': commit_delay }
        
        result = self.sendReq(url, 'POST', query)
        result_json = json.load(result)
        
        if commit_pending_ops:
            self.commit_pending_ops()
        return result_json
    
    def addOpsToView(self, viewId, opinionIdsList):
        url = self.base_addr + '/view/add_opinions'
        query = {'opinion_ids': " ".join(opinionIdsList),
                 'view_id': viewId,
                 'access_token' : self.accessToken}
        
        result = self.sendReq(url, 'POST', query)
        resultJson = json.load(result)
        return resultJson
    
    def get_path_to_opinion(self, parent_id, child_id, max_content_length = 0):
        url = self.base_addr + '/opinion/get_path_to_opinion'
        query = {'parent_op': parent_id,
                 'child_op': child_id,
                 'access_token' : self.accessToken}
        if max_content_length:
            query['max_content_length'] = max_content_length
        result = self.sendReq(url, 'GET', query)
        resultJson = json.load(result)
        return resultJson
    
    #Some more complicated stuff
    def authAndCreateOp(self, baseOpId, parent, evaluation, **kwargs):
        self.authorize('commenter' + str(self.commenterId), 'emptypass', 'all:rc')
        self.commenterId += 1
        return self.createOp(parent, evaluation, **kwargs)
    
    
    